package com.testspring.service;

import com.handspring.MyBeanPostProcessor;
import com.handspring.MyComponent;
import com.testspring.ZhengValue;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author: ztl
 * @date: 2024/05/07 22:38
 * @desc: 写一个类，去实现我自己定义的，类似于spring中的  beanPostProcessor 的类
 *  todo： 注意，beanPostProcessor 非常重要，几乎是spring中最重要的了。
 *          像aop、依赖注入，几乎底层都是他
 *              aop 原理
 */

@MyComponent
public class ZtlMyBeanPostProcessor implements MyBeanPostProcessor {

    /**
     * 做前置操作
     * @param bean      要操作的对象
     * @param beanName  要操作的bean的，beanName
     * @return
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws IllegalAccessException {
        // 操作属性赋值-实现beanNameAware的回调功能
        for (Field field : bean.getClass().getDeclaredFields()){
            if (field.isAnnotationPresent(ZhengValue.class)){
                field.setAccessible(true);
                // 赋值，赋什么值呢，我们自定义注解中的value值
                field.set(bean,field.getAnnotation(ZhengValue.class).value());
            }
        }


        // 你在这，也可以针对某一个key做处理，比如说我只想对userService做处理
        if ("userServiceAop".equals(beanName)){
            System.out.println("注意注意注意，aop原理-我执行了beanPostProcessor的前置操作");
            // 类加载器 ； 当前类有那些接口，我就代理哪些接口 ；具体的代理逻辑
            Object proxyInstance = Proxy.newProxyInstance(ZtlMyBeanPostProcessor.class.getClassLoader(),
                    bean.getClass().getInterfaces(), new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                    // 执行的切面逻辑：
                    System.out.println("我执行了具体的切面逻辑--aop");

                    // 注意，这里的对象传的是原始的bean对象(userService)，而不是传代理对象(userService的代理类)
                    return method.invoke(bean,args);
                }
            });

            // 返回我的代理对象
            return proxyInstance;
        }

        return bean;


    }

}
